#include <iostream>
#include <vector>
#include <thread>
#include <atomic>
#include <random>
#include <time.h>
#include "../ConcurrentAlloc/ConcurrentAlloc.h"
// ntimes 一轮申请和释放内存的次数
// rounds 轮次
// nworks 线程数量
extern void PrintRatio();
void BenchmarkMalloc(size_t ntimes, size_t nworks, size_t rounds)
{
	std::vector<std::thread> vthread(nworks);
	std::atomic<size_t> malloc_costtime(0);
	std::atomic<size_t> free_costtime(0);

	for (size_t k = 0; k < nworks; ++k)
	{
		vthread[k] = std::thread([&, k]()
								 {
			std::vector<void *> v;
			v.reserve(ntimes);

			// 1. 选择种子：使用非确定性源（系统熵池）
			std::random_device rd;

			// 2. 创建引擎：使用 mt19937 算法，并用种子初始化
			std::mt19937 gen(rd());

			// 3. 创建分布器：指定均匀整数分布的范围 [min, max]
			std::uniform_int_distribution<> distrib(0, 256 * 1024 / 10);
			// 4. 生成数字：将引擎 gen 传入分布器 distrib
			// int random_num = distrib(gen);
			for (size_t j = 0; j < rounds; ++j)
			{
			size_t begin1 = clock();
			for (size_t i = 0; i < ntimes; i++)
			{
				// v.push_back(malloc(16));
				// v.push_back(malloc((size_t)distrib(gen)));
				   v.push_back(malloc(i + 1));
			}

			for(size_t i = 0;i < 10;i++)
			{
				v.push_back(malloc(MAX_BYTES + 8 * 1024));
			}
			for(size_t i = 0;i < 10;i++)
			{
				v.push_back(malloc(129 * 8 * 1024));
			}
			size_t end1 = clock();

			size_t begin2 = clock();
			size_t i = 0;
			for (; i < ntimes; i++)
			{
				free(v[i]);
			}
			for(;i < ntimes + 10;i++)
			{
				free(v[i]);
			}
			for(;i < ntimes + 10;i++)
			{
				free(v[i]);
			}
			size_t end2 = clock();
			v.clear();

			malloc_costtime += (end1 - begin1);
			free_costtime += (end2 - begin2);

			} });
	}

	for (auto &t : vthread)
	{
		t.join();
	}

	printf("%lu个线程并发执行%lu轮次,每轮次malloc %lu次:花费：%lu ns\n",
		   nworks, rounds, ntimes, malloc_costtime.load());

	printf("%lu个线程并发执行%lu轮次,每轮次free %lu次:花费：%lu ns\n",
		   nworks, rounds, ntimes, free_costtime.load());

	printf("%lu个线程并发malloc&free %lu次,总计花费:%lu ns\n",
		   nworks, nworks * rounds * ntimes, malloc_costtime.load() + free_costtime.load());

	// printf("%u个线程并发执行%u轮次,每轮次ConcurrentAlloc %u次:花费：%u ms\n",
	// 	nworks, rounds, ntimes, malloc_costtime.load());

	// printf("%u个线程并发执行%u轮次,每轮次ConcurrentFree %u次:花费：%u ms\n",
	// 	nworks, rounds, ntimes, free_costtime.load());

	// printf("%u个线程并发ConcurrentAlloc&ConcurrentFree %u次,总计花费:%u ms\n",
	// 	nworks, nworks*rounds*ntimes, malloc_costtime.load() + free_costtime.load());
}

// 单轮次申请释放次数 线程数 轮次
void BenchmarkConcurrentMalloc(size_t ntimes, size_t nworks, size_t rounds)
{
	std::vector<std::thread> vthread(nworks);
	std::atomic<size_t> malloc_costtime(0);
	std::atomic<size_t> free_costtime(0);

	for (size_t k = 0; k < nworks; ++k)
	{
		vthread[k] = std::thread([&]()
								 {
			std::vector<void*> v1;
			std::vector<int> v2;
			v1.reserve(ntimes);
			v2.reserve(ntimes);
			// 1. 选择种子：使用非确定性源（系统熵池）
			std::random_device rd;

			// 2. 创建引擎：使用 mt19937 算法，并用种子初始化
			std::mt19937 gen(rd());

			// 3. 创建分布器：指定均匀整数分布的范围 [min, max]
			std::uniform_int_distribution<> distrib(1, 256 * 1024 / 10);
			// // 4. 生成数字：将引擎 gen 传入分布器 distrib
			// // int random_num = distrib(gen);
			for (size_t j = 0; j < rounds; ++j)
			{
				size_t begin1 = clock();
				for (size_t i = 0; i < ntimes; i++)
				{
					// v.push_back(ConcurrentAlloc(8));
					v1.push_back(ConcurrentAlloc(i + 1));
					// size_t bytes = (size_t)distrib(gen);
					// v1.push_back(ConcurrentAlloc(bytes));
					// v2.push_back(bytes);
				}
				for(size_t i = 0;i < 10;i++)
				{
					v1.push_back(ConcurrentAlloc(MAX_BYTES + 8 * 1024));
				}
				for(size_t i = 0;i < 10;i++)
				{
					v1.push_back(ConcurrentAlloc(129 * 8 * 1024));
				}
				size_t end1 = clock();

				size_t begin2 = clock();
				size_t i = 0;
				for (; i < ntimes; i++)
				{
					// ConcurrentFree(v[i],8);
					// ConcurrentFree(v1[i],v2[i]);
					ConcurrentFree(v1[i]);
				}
				for(;i < ntimes + 10;i++)
				{
					ConcurrentFree(v1[i]);
				}
				for(;i < ntimes + 10;i++)
				{
					ConcurrentFree(v1[i]);
				}
				size_t end2 = clock();
				v1.clear();
				v2.clear();
				malloc_costtime += (end1 - begin1);
				free_costtime += (end2 - begin2);
			} 
			// PrintRatio();
		});
	}

	for (auto &t : vthread)
	{
		t.join();
	}

	printf("%lu个线程并发执行%lu轮次,每轮次ConcurrentAlloc %lu次:花费：%lu ns\n",
		   nworks, rounds, ntimes, malloc_costtime.load());

	printf("%lu个线程并发执行%lu轮次,每轮次ConcurrentFree %lu次:花费：%lu ns\n",
		   nworks, rounds, ntimes, free_costtime.load());

	printf("%lu个线程并发ConcurrentAlloc&ConcurrentFree %lu次,总计花费:%lu ns\n",
		   nworks, nworks * rounds * ntimes, malloc_costtime.load() + free_costtime.load());

	// printf("%u个线程并发执行%u轮次,每轮次ConcurrentAlloc %u次:花费：%u ms\n",
	// 	nworks, rounds, ntimes, malloc_costtime.load());

	// printf("%u个线程并发执行%u轮次,每轮次ConcurrentFree %u次:花费：%u ms\n",
	// 	nworks, rounds, ntimes, free_costtime.load());

	// printf("%u个线程并发ConcurrentAlloc&ConcurrentFree %u次,总计花费:%u ms\n",
	// 	nworks, nworks*rounds*ntimes, malloc_costtime.load() + free_costtime.load());
}

int main()
{
	size_t n = 10000;
	cout << "==========================================================" << endl;
	BenchmarkConcurrentMalloc(n, 5, 10);
	cout << endl<< endl;

	BenchmarkMalloc(n, 5, 10);
	cout << "==========================================================" << endl;

	return 0;
}
